package com.immediatus.util;

public class PooledLinkedList<T>{
    static final class Item<T> extends PoolItem{
        public T payload;
        public Item<T> next;
        public Item<T> prev;
    }

    private final Pool<Item<T>> _pool;
    private Item<T> _head;
    private Item<T> _tail;
    private Item<T> _iter;
    private Item<T> _current;
    private int _size = 0;

    public PooledLinkedList(int maxSize_){
        this._pool = new Pool<Item<T>>(maxSize_){
            @Override
            protected Item<T> onAllocatePoolItem(){
                return new Item<T>();
            }
        };
    }

    public void add(T obj_){
        Item<T> item = _pool.obtainPoolItem();
        item.payload = obj_;
        item.next = null;
        item.prev = null;

        if (this._head == null){
            this._head = item;
            this._tail = item;
            this._size++;
            return;
        }

        item.prev = this._tail;
        this._tail.next = item;
        this._tail = item;
        this._size++;
    }

    public void iter(){
        this._iter = this._head;
    }

    public T next(){
        if (this._iter == null) return null;

        T payload = this._iter.payload;
        this._current = this._iter;
        this._iter = this._iter.next;
        return payload;
    }

    public void remove(){
        if (this._current == null) return;

        this._size--;
        this._pool.recycle(this._current);

        Item<T> current = this._current;
        Item<T> next = this._current.next;
        Item<T> prev = this._current.prev;
        this._current = null;

        if (this._size == 0){
            this._head = null;
            this._tail = null;
            return;
        }

        if (current == this._head){
            next.prev = null;
            this._head = next;
            return;
        }

        if (current == this._tail){
            prev.next = null;
            this._tail = prev;
            return;
        }

        prev.next = next;
        next.prev = prev;
    }

    public void clear(){
        iter();
        T v = null;
        while ((v = next()) != null) remove();

    }
}
